#pragma once
#include "timeout_exception.hpp"
#include <functional>
#include <future>
#include <atomic>
#include <memory>
#include <type_traits>
#include <iostream>

namespace timeout_manager {

/**
 * 任务状态枚举
 */
enum class TaskStatus {
    PENDING,    // 等待执行
    RUNNING,    // 正在执行
    COMPLETED,  // 已完成
    CANCELLED,  // 已取消
    TIMEOUT     // 已超时
};

/**
 * 将枚举转换为字符串（用于调试）
 */
inline const char* taskStatusToString(TaskStatus status) {
    switch (status) {
        case TaskStatus::PENDING:   return "PENDING";
        case TaskStatus::RUNNING:   return "RUNNING";
        case TaskStatus::COMPLETED: return "COMPLETED";
        case TaskStatus::CANCELLED: return "CANCELLED";
        case TaskStatus::TIMEOUT:   return "TIMEOUT";
        default: return "UNKNOWN";
    }
}

/**
 * 任务包装器模板类
 * 
 * 这个类的作用：
 * 1. 包装用户提供的函数，使其可以被统一管理
 * 2. 提供取消、超时等控制功能
 * 3. 通过promise/future机制异步获取执行结果
 * 4. 处理执行过程中的异常
 * 
 * @tparam R 函数返回类型
 */
template<typename R>
class TaskWrapper {
public:
    using TaskFunc = std::function<R()>;  // 任务函数类型
    using Promise = std::promise<R>;      // Promise类型
    using Future = std::future<R>;        // Future类型
    
    /**
     * 构造函数
     * @param id 任务唯一标识
     * @param task 要执行的任务函数
     */
    TaskWrapper(uint64_t id, TaskFunc task);
    
    /**
     * 析构函数
     */
    ~TaskWrapper();
    
    /**
     * 执行任务
     * 这个函数会在工作线程中被调用
     */
    void execute();
    
    /**
     * 取消任务
     * 如果任务还没开始执行，会阻止其执行
     * 如果任务正在执行，会设置取消标志（但不能强制停止）
     */
    void cancel();
    
    /**
     * 设置任务超时
     * 这个函数通常由定时器线程调用
     */
    void timeout();
    
    /**
     * 获取任务结果的future对象
     * @return future对象，可以用来异步获取任务结果
     */
    Future getFuture();
    
    /**
     * 获取任务ID
     */
    uint64_t getId() const { return task_id_; }
    
    /**
     * 获取当前任务状态
     */
    TaskStatus getStatus() const { return status_.load(); }
    
    /**
     * 检查任务是否应该取消
     * 任务函数可以定期调用这个函数来检查是否需要提前退出
     */
    bool shouldCancel() const { 
        auto status = status_.load();
        return status == TaskStatus::CANCELLED || status == TaskStatus::TIMEOUT;
    }
    
private:
    /**
     * 尝试将状态从from变更为to
     * @param from 期望的当前状态
     * @param to 要设置的新状态
     * @return 是否成功变更
     */
    bool tryChangeStatus(TaskStatus from, TaskStatus to);
    
    /**
     * 设置异常到promise中
     */
    void setException(const std::exception_ptr& ex);
    
    uint64_t task_id_;                    // 任务唯一标识
    TaskFunc task_;                       // 要执行的任务函数
    std::unique_ptr<Promise> promise_;    // 用于传递结果的promise
    std::atomic<TaskStatus> status_;      // 任务当前状态
};

/**
 * 构造函数实现
 */
template<typename R>
TaskWrapper<R>::TaskWrapper(uint64_t id, TaskFunc task) 
    : task_id_(id), 
      task_(std::move(task)), 
      promise_(std::make_unique<Promise>()),
      status_(TaskStatus::PENDING) {
    
    std::cout << "创建任务包装器: ID=" << task_id_ << " (TaskWrapper<R>::TaskWrapper)"<< std::endl;
}

/**
 * 析构函数实现
 */
template<typename R>
TaskWrapper<R>::~TaskWrapper() {
    std::cout << "销毁任务包装器: ID=" << task_id_ 
              << ", 最终状态=" << taskStatusToString(status_.load()) <<" (TaskWrapper<R>::~TaskWrapper)" << std::endl;
    
    // 如果任务还在等待状态，设置为取消状态并通知等待者
    if (status_.load() == TaskStatus::PENDING) {
        cancel();
    }
}

/**
 * 执行任务
 */
template<typename R>
void TaskWrapper<R>::execute() {
    std::cout << "开始执行任务: ID=" << task_id_ << " (TaskWrapper<R>::execute)"<<std::endl;
    
    // 尝试将状态从PENDING改为RUNNING
    if (!tryChangeStatus(TaskStatus::PENDING, TaskStatus::RUNNING)) {
        // 如果状态变更失败，说明任务已经被取消或超时
        std::cout << "任务无法执行，当前状态: " 
                  << taskStatusToString(status_.load()) 
                  << ", ID=" << task_id_ << " (TaskWrapper<R>::execute)"<< std::endl;
        return;
    }
    
    try {
        // 执行任务函数
        if constexpr (std::is_void_v<R>) {
            // 处理无返回值的函数
            task_();
            
            // 检查是否在执行过程中被取消或超时
            if (tryChangeStatus(TaskStatus::RUNNING, TaskStatus::COMPLETED)) {
                promise_->set_value();
                std::cout << "任务执行完成: ID=" << task_id_ << " (TaskWrapper<R>::execute)"<< std::endl;
            } else {
                std::cout << "任务执行完成但状态已改变: ID=" << task_id_ 
                          << ", 状态=" << taskStatusToString(status_.load()) << " (TaskWrapper<R>::execute)"<< std::endl;
            }
        } else {
            // 处理有返回值的函数
            auto result = task_();
            
            // 检查是否在执行过程中被取消或超时
            if (tryChangeStatus(TaskStatus::RUNNING, TaskStatus::COMPLETED)) {
                promise_->set_value(std::move(result));
                std::cout << "任务执行完成并返回结果: ID=" << task_id_  << " (TaskWrapper<R>::execute)"<< std::endl;
            } else {
                std::cout << "任务执行完成但状态已改变，丢弃结果: ID=" << task_id_ 
                          << ", 状态=" << taskStatusToString(status_.load())  << " (TaskWrapper<R>::execute)"<< std::endl;
            }
        }
        
    } catch (const std::exception& e) {
        std::cout << "任务执行异常: ID=" << task_id_ << ", 错误=" << e.what()  << " (TaskWrapper<R>::execute)"<< std::endl;
        
        if (tryChangeStatus(TaskStatus::RUNNING, TaskStatus::COMPLETED)) {
            setException(std::current_exception());
        }
    } catch (...) {
        std::cout << "任务执行未知异常: ID=" << task_id_  << " (TaskWrapper<R>::execute)"<< std::endl;
        
        if (tryChangeStatus(TaskStatus::RUNNING, TaskStatus::COMPLETED)) {
            setException(std::current_exception());
        }
    }
    std::cout<< "任务执行结束: ID=" << task_id_ << " (TaskWrapper<R>::execute)"<< std::endl;
}

/**
 * 取消任务
 */
template<typename R>
void TaskWrapper<R>::cancel() {
    auto oldStatus = status_.load();
    
    if (oldStatus == TaskStatus::COMPLETED || oldStatus == TaskStatus::TIMEOUT) {
        // 任务已经完成或超时，无法取消
        std::cout << "任务无法取消，当前状态: " 
                  << taskStatusToString(oldStatus) 
                  << ", ID=" << task_id_ << " (TaskWrapper<R>::cancel)"<< std::endl;
        return;
    }
    
    // 尝试设置为取消状态
    if (status_.compare_exchange_strong(oldStatus, TaskStatus::CANCELLED)) {
        std::cout << "任务已取消: ID=" << task_id_ 
                  << ", 之前状态=" << taskStatusToString(oldStatus) << " (TaskWrapper<R>::cancel)"<< std::endl;
        
        // 设置异常到promise
        setException(std::make_exception_ptr(
            TimeoutException("Task was cancelled before execution")
        ));
    } else {
        // 如果CAS失败，说明状态在我们检查后被其他线程改变了
        // 递归重试
        cancel();
    }
}

/**
 * 设置任务超时
 */
template<typename R>
void TaskWrapper<R>::timeout() {
    auto oldStatus = status_.load();
    
    if (oldStatus == TaskStatus::COMPLETED || oldStatus == TaskStatus::CANCELLED) {
        // 任务已经完成或取消，无法设置超时
        std::cout << "任务无法设置超时，当前状态: " 
                  << taskStatusToString(oldStatus) 
                  << ", ID=" << task_id_ << " (TaskWrapper<R>::timeout)"<<std::endl;
        return;
    }
    
    // 尝试设置为超时状态
    if (status_.compare_exchange_strong(oldStatus, TaskStatus::TIMEOUT)) {
        std::cout << "任务已超时: ID=" << task_id_ 
                  << ", 之前状态=" << taskStatusToString(oldStatus) << " (TaskWrapper<R>::timeout)"<< std::endl;
        
        // 设置异常到promise
        setException(std::make_exception_ptr(
            TimeoutException("Task execution timed out")
        ));
    } else {
        // 递归重试
        timeout();
    }
}

/**
 * 获取Future对象
 */
template<typename R>
typename TaskWrapper<R>::Future TaskWrapper<R>::getFuture() {
    return promise_->get_future();
}

/**
 * 尝试改变状态
 */
template<typename R>
bool TaskWrapper<R>::tryChangeStatus(TaskStatus from, TaskStatus to) {
    bool success = status_.compare_exchange_strong(from, to);
    if (success) {
        std::cout << "任务状态变更: ID=" << task_id_ 
                  << ", " << taskStatusToString(from) 
                  << " -> " << taskStatusToString(to) << " (TaskWrapper<R>::tryChangeStatus)"<< std::endl;
    }
    return success;
}

/**
 * 设置异常
 */
template<typename R>
void TaskWrapper<R>::setException(const std::exception_ptr& ex) {
    try {
        promise_->set_exception(ex);
    } catch (const std::future_error& e) {
        // promise可能已经设置过值了
        std::cout << "设置异常失败: ID=" << task_id_ 
                  << ", 错误=" << e.what()<< " (TaskWrapper<R>::setException)" << std::endl;
    }
}

} // namespace timeout_manager